#include<bits/stdc++.h>
#define ll long long
#define mid ((l+r)>>1)
#define ls (x<<1)
#define rs ((x<<1)|1)
using namespace std;
namespace IO{
    char buff[1<<21],*p1=buff,*p2=buff;
    char getch(){
        return p1==p2&&(p2=((p1=buff)+fread(buff,1,1<<21,stdin)),p1==p2)?EOF:*p1++;
    }
    template<typename T>
    void read(T &x){
        char ch=getch();int fl=1;x=0;
        while(ch>'9'||ch<'0'){if(ch=='-')fl=-1;ch=getch();}
        while(ch<='9'&&ch>='0'){x=x*10+ch-48;ch=getch();}
        x*=fl;
    }
    template<typename T,typename ...Args>
    void read(T &x,Args& ...args){
        read(x);read(args...);
    }
    char obuf[1<<21],*p3=obuf;
    void putch(char ch){
        if(p3-obuf<(1<<21))*p3++=ch;
        else fwrite(obuf,p3-obuf,1,stdout),p3=obuf,*p3++=ch;
    }
    void pc(const char *s){
    	while(*s)putch(*s),s++;
    }
    char ch[100];
    template<typename T>
    void write(T x){
        if(!x)return putch('0');
        if(x<0)putch('-'),x*=-1;
        int top=0;
        while(x)ch[++top]=x%10+48,x/=10;
        while(top)putch(ch[top]),top--;
    }
    template<typename T,typename ...Args>
    void write(T x,Args ...args){
        write(x),putch(' '),write(args...);
    }
    void flush(){fwrite(obuf,p3-obuf,1,stdout);}
}
using namespace IO;
const int N=2005;
int n;
int a[N],b[N];
struct BIT1{
	int tree[N];
	inline int lowbit(int x){return x&(-x);}
	inline void Init(){
		memset(tree,0,sizeof tree);
		return;
	}
	inline void add(int x,int y){
		x++;
		while(x<=n+2){
			tree[x]=max(tree[x],y);
			x+=lowbit(x);
		}
	}
	inline int ask(int x){
		x++;
		int sum=0;
		while(x){
			sum=max(sum,tree[x]);
			x-=lowbit(x);
		}
		return sum;
	}
}T1[N];
struct BIT2{
	int tree[N];
	inline int lowbit(int x){return x&(-x);}
	inline void Init(){
		memset(tree,0,sizeof tree);
		return;
	}
	inline void add(int x,int y){
		x++;
		while(x){
			tree[x]=max(tree[x],y);
			x-=lowbit(x);
		}
	}
	inline int ask(int x){
		x++;
		int sum=0;
		while(x<=n+2){
			sum=max(sum,tree[x]);
			x+=lowbit(x);
		}
		return sum;
	}
}T2[N];
//struct SGT{
//	int tree[N<<2],tag[N<<2];
//	inline void add(int x,int v){
//		tree[x]=max(tree[x],v);
//		tag[x]=max(tag[x],v);
//	}
//	inline void push_down(int x){
//		return add(ls,tag[x]),add(rs,tag[x]),tag[x]=0;
//	}
//	void modify(int x,int l,int r,int L,int R,int v){
//		if(L<=l&&r<=R)add(x,v);
//		push_down(x);
//		if(L<=mid)modify(ls,l,mid,L,R,v);
//		if(R>mid)modify(rs,mid+1,r,L,R,v);
//		tree[x]=max(tree[ls]+tree[rs]);
//	}
//	int query(int x,int l,int r,int L,int R){
//		if(L<=l&&r<=R)return tree[x];
//		push_down(x);
//		if(R<=mid)return query(ls,l,mid,L,R);
//		else if(L>mid)return query(rs,mid+1,r,L,R);
//		else return max(query(ls,l,mid,L,R),query(rs,mid+1,r,L,R));
//	}
//}T1,T2;
//int f[N],g[N];
signed main(){
	freopen("shung.in","r",stdin);
	freopen("shung.out","w",stdout);
	read(n);
	for(int i=1;i<=n;i++)
		read(a[i]);
	for(int i=1;i<=n;i++){
		vector<pair<pair<int,int>,int>>s;
		for(int j=0;j<=n+1;j++){
			int x=T1[j].ask(a[i]-1)+1;
			s.push_back({{j,a[i]},x});
		}
		for(int j=0;j<=n+1;j++){
			int x=T2[j].ask(a[i]+1)+1;
			s.push_back({{a[i],j},x});
		}
		for(auto p:s){
			T1[p.first.first].add(p.first.second,p.second);
			T2[p.first.second].add(p.first.first,p.second);
		}
		s.clear();
	}
	int ans=0;
	for(int i=0;i<=n+1;i++)
		ans=max(ans,T1[i].ask(n+1));
//	for(int i=1;i<=n;i++)
//		b[a[i]]=i;
//	T.Init(); 
//	for(int i=n;i>=1;i--){
//		g[i]=T.ask(a[i])+1;
//		T.add(a[i],g[i]);
//	}
//	T.Init(); 
//	for(int i=n;i>=1;i--){
//		f[i]=T.ask(n-a[i]+1)+1;
//		T.add(n-a[i]+1,f[i]);
//	}
//	int ans=0;
//	T1.modify(1,0,n+1,n+1,n+1,1);
//	T2.modify(1,0,n+1,0,0,1);
//	for(int i=2;i<=n;i++){
//		if(a[i-1]<a[i]){
//			ans=max(ans,T1.query(1,0,n+1,0,a[i]-1)+f[i]+g[i-1]-2);
//		}else{
//			ans=max(ans,T2.query(1,0,n+1,a[i]+1,n+1)+f[i-1]+g[i]-2);
//		}
//		work(i);
//	}
	write(ans);
	return flush(),0;
}

